package com.tedu.API.map;
import org.junit.Test;

import java.util.*;
import java.util.function.BiConsumer;

/** 包位置: java.util
 * Map顶级映射接口:
 * 作用: 一个元素由两个对象构成，分别键:Key与值: Value;
 *      保存一个元素: Key---Value【保存一对: 两个对象】
 * 用途: 通常与数据库搭配使用
 * 特点: 键: 无序、无下标、不可重复，实际存HashSet
 *      值: 存泛型约束的类型，可以重复，实际存Collection
 * Map 接口对象创建---实现类:
 * HashMap:        【常用:HashMap方法与Map方法类似】
 *          由键值对组成，使用哈希算法实现!
 *          键与值可以为null,键中值允许一个null!
 * LinkedHashMap: 【不常用: 方法与HashMap类似】 两端插入和增加，效率较高
 * TreeMap:【不用】  【算法: 红黑树】 性能: 效率较低、线程非常安全
 * HashTable:【不用】  jok1.0版本，由哈希算法实现，解决多线程问题
 * ConcurrentHashMap: 【常用】  多线程
 */
public class MapAPI {
    @Test
    public void testMap(){
        //创建Map映射集合接口
        Map<Object,String> map=new HashMap<>();
        /**
         * put(键K，值V)    返回值: V value---实际Collection
         * 作用: 映射集合存入一对元素: 键与值
         */
        map.put("西游记","孙悟空");  //Key键: Set集合: 无序、无下标、唯一
        map.put("红楼梦","林黛玉");  //Key键值一样，进行覆盖
        map.put("水浒传","宋公明");
        map.put("三国志","诸葛亮");
        map.put("红楼梦","贾宝玉");
        map.put(null,"无名氏");
        map.put(null,"无名氏");
        System.out.println("Map集合"+map);

        //需求: 获取一组元素当中的值:"林黛玉"  get(键)  通过键找到值 返回值: V
        String lin=map.get("红楼梦");
        System.out.println("通过键找到对应值: "+lin);
        //没有这个键，自动按照Collection对象，补对象默认: null
        System.out.println("通过键找值【键不存在】" +map.get("三国"));

        //删除元素中: 键    remove(Key)   返回值: V  value Collection
        map.remove("红楼梦");
        System.out.println("Map集合: "+map);

        //size() 获取映射集合的元素个数
        System.out.println("Map元素总数: "+map.size());

        //containsKey()    判断键是否存在  返回值: boolean
        //containsValue()  判断值是否存在  返回值: boolean
        boolean b=map.containsKey("三国志");
        System.out.println("判断键是否存在: "+b);
        boolean v= map.containsValue("宋公明");
        System.out.println("判断值是否存在: "+v);
    }

    /**
     * Map映射集合中: 一组键值对存入【一组元素: Entry】
     * 遍历映射集合:  遍历所有的键   遍历所有的值   遍历所有的Entry
     * keySet:  获取集合当中所有的键
     * values:  获取集合当中所有的值
     * entry:   获取集合当中所有的entry【键与值】
     */
    @Test
    public void testMaps(){
        Map<Object,String> map=new HashMap<>();
        map.put("福建","佛跳墙");
        map.put("北京","北京烤鸭");
        map.put("四川","开水白菜");
        map.put("湖南","玉麟香腰");
        //1.keySet()  获取所有的键值
        Set<Object> set=map.keySet();
        //遍历所有的键: 增强for
        for (Object o:set){ //从set集合获取到所有键
            System.out.println("获取所有的键: "+o);
        }
        //2.values()  获取所有值
        Collection<String> str=map.values();
        //遍历所有的值: 增强for: 获取集合的所有元素
        for (String s:str ) {
            System.out.println("获取所有的值: "+s);
        }

        //3.entrySet()  获取所有的Entry键值
        //返回值: Set<Map.Entry<K,V>>
        //Entry类型: Map.Entry<K,V>
        //Entry存键值的对象---Map增加一个针对"键值对"的对象
        //Map.Entry    【Map接口.Entry对象】获取到所有的Entry的方法
        Set<Map.Entry<Object,String>> sets=map.entrySet();
        //获取所有的【Entry】键值对
        for (Map.Entry<Object,String> s:sets){
            //System.out.println("所有的entry: "+s);
            //Entry中  Key  与  Value方法: getKey()  getValue()
            Object key=s.getKey();
            String value=s.getValue();
            System.out.println("打印Entry中键与值"+key+" "+value);
        }
    }

    /**
     * forEach(new BiConsumer())
     * BiConsumer  接口  ---封装了Entry对象的键与值
     * 作用: 遍历出集合中所有的entry【键与值】
     */
    @Test
    public void testForEach(){
        Map<Object,String> map=new HashMap<>();
        map.put("福建","佛跳墙");
        map.put("北京","北京烤鸭");
        map.put("四川","开水白菜");
        map.put("湖南","玉麟香腰");
        //forEach(接口) 遍历映射集合: 键与值
        map.forEach(new BiConsumer<Object,String>(){
            //accept(K,V)  获取Entry中所有的值
            public void accept(Object o, String s) {
                System.out.println("所有的键: "+o);
                System.out.println("所有的值: "+s);
            }
        });
    }

    /**
     * putIfAbsent()
     * 作用: 存一组entry,先判断指定的键是否存在，不存在将键值插入
     *                                      存在键值不插入
     */
    @Test
    public void testHashMap(){
        Map<Object,String> map=new HashMap<>();
        map.put("福建","佛跳墙");
        map.put("北京","北京烤鸭");
        map.put("四川","开水白菜");
        map.put("湖南","玉麟香腰");
        map.put("山西","子推燕");
        map.putIfAbsent("浙江","龙井虾仁");
        map.putIfAbsent("福建","鸡茸金丝笋");     //相同键   不插入
        System.out.println("HashMap集合: "+map);
    }
}
